home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource4 / 228_01 / eraq.c < prev    next >
Text File  |  1987-07-31  |  11KB  |  423 lines

  1. /*
  2. HEADER:         CUGXXX;
  3. TITLE:          ERAQ for MS-DOS;
  4. DATE:           4-6-87;
  5. DESCRIPTION:    Finds file(s) in tree, prompting for erase/keep.
  6. KEYWORDS:       Disk organizer;
  7. FILENAME:       ERAQ.C;
  8. WARNINGS:       For MS-DOS and Lattice on Compaq;
  9. AUTHORS:        John Welch;
  10. COMPILER:       Lattice C;
  11. REFERENCES:     US-DISK 1310;
  12. ENDREF
  13. */
  14. /* ERAQ.C  a program to traverse DOS's tree-structured directory, looking
  15.    for the file(s) specified. They are then displayed on the screen
  16.    and the user is prompted for ERASE or NOT ERASE. Basically, I got
  17.    damned tired of DOS not having an ERAQ like CPM.
  18.     The basic traverse from directory to directory portion is a
  19.    very versatile toy around which many useful utilities can (and will,
  20.    I'm sure!) be written. Here's one of them. I'll do more as time
  21.    and inclination permits, but I'll turn this one loose first because
  22.    I think it's useful.
  23.     This is written for MSDOS 2.0 or better, using the LATTICE C Compiler,
  24.    on a Compaq. 7-20-84 jjw
  25.    ps I know this could be shortened drastically and speeded up by
  26.    combining some of the modules into larger functions, but this way was
  27.    much easier to write & de-bug modularly and so I left it that way. Also,
  28.    some of the modules might be useful in themselves to build into a
  29.    library. This program differs from most C code I've seen before because
  30.    1.) it does something useful.
  31.    2.) it does not have pointers to pointers to arrays of pointers to functions
  32.        returning pointers. It is easy and straight-forward, at the expense of
  33.        some speed and length.
  34.    3.) it is commented. Not extensively, but fairly well. The hard parts have
  35.        to do with the dirstak, which is not a stack but a queue (dirqueue
  36.        looked too silly to me and d_queue made me think of peanut buster
  37.        parfaits). If puzzled, follow it through but keep the msdos manual
  38.        handy to see what byte is what.
  39.    If you have any questions about this, drop me a note. I frequent almost
  40.    every tech-oriented CPM bulletin board around Chicago, Il.
  41.    Name is John Welch, or just jjw.
  42.        2397 John Smith Dr. Apt B
  43.        Schaumburg, Il 60194 */
  44.  
  45. #include "dos.h"
  46. #include "stdio.h"
  47.  
  48. main(argc,argv)
  49. int argc;
  50. char *argv[];
  51. {
  52. char look[15],start[100],init_dir[100],drive[2],flag1,stuff[100];
  53. int first,last,temp,temp1,ret;
  54.  
  55. printf("ERAQ.C Ver 1.00 1-25-85 John J. Welch\n");
  56. printf("(for help, type ERAQ HELP)\n\n");
  57.  
  58. if (argc == 1)
  59.  {
  60.   /* get the filename to erase */
  61.   printf("Filename to be erased -->");
  62.   scanf("%s",look);
  63.  
  64.   /* get the drive we're going to do the erasing on */
  65.   printf("Enter the drive letter -->");
  66.   scanf("%s",stuff);
  67.   drive[1] = stuff[0];
  68.  
  69.   /* get starting directory */
  70.   printf("Directory to start in (absolute path from root) -->");
  71.   scanf("%s",start);
  72.  
  73.   /* do we want to do all sub-directories, too, or just this one? */
  74.   printf("Traverse all sub-directories under this one -->");
  75.   scanf("%s",stuff);
  76.   if ((stuff[0] == 'y') || (stuff[0] == 'Y'))
  77.    flag1 = 1; /* if they specified Y, set the flag */
  78.   else
  79.    flag1 = 0; /* anything but Y or y means NO */
  80.  
  81.   }
  82. else
  83.  {
  84.   if (argc != 2)
  85.    {
  86. HERE:
  87.     printf("For prompts, just type ERAQ.\n");
  88.     printf("Command line syntax is ERAQ  [drive:][starting path]file.ext[/y]\n");
  89.     printf("where [drive:] is optional drive,\n");
  90.     printf("  [starting path] is optional path to start at,\n");
  91.     printf("  file.ext is the file name (wildcards ok) to delete,\n");
  92.     printf("  [/y] is optionally if you want to do all sub-directories under the\n");
  93.     printf("  starting directory (default value is no).\n");
  94.     return;
  95.    }
  96.   else
  97.    {
  98.     if ((strcmp(argv[1],"HELP") == 0) || (strcmp(argv[1],"help") == 0))
  99.      goto HERE;
  100.  
  101.     first = 0; /* first character of the command line */
  102.     drive[1] = 255; /* set up to default to current drive */
  103.     flag1 = 0; /* default it to not do sub-dirs */
  104.     if (argv[1][1] == ':') /* if there was a drive specified, pick the letter */
  105.     { /*off and store it someplace */
  106.      drive[1] = argv[1][0];
  107.      first = 2; /* now, the first character in the command line is #2 */
  108.     }
  109.     last = strlen(argv[1]); /* get the length of the command line */
  110.     if (argv[1][last-2] == '/') /* if they used the toggle, set it up */
  111.     {
  112.      if ((argv[1][last-1] == 'y') || (argv[1][last-1] == 'Y'))
  113.       flag1 = 1; /* if they specified Y, set the flag */
  114.      else
  115.       flag1 = 0; /* anything but Y or y means NO */
  116.      last -= 2; /* bump the last character down */
  117.      argv[1][last] = 0; /* and now, null terminate the command line */
  118.     }
  119.  
  120.     for (temp = last; ((argv[1][temp] != ':') && (temp >= first) && (argv[1][temp] != '\\')); temp--); /* find last \ */
  121.  
  122.     for (temp1 = first; temp1 < temp+1; temp1++) /* get pathname (if any) */
  123.     {start[temp1-first] = argv[1][temp1];}
  124.     start[temp1-first] = 0; /* null terminate it */
  125.  
  126.     for (temp1 = temp+1; temp1 <= last; temp1++) /* get the filename to look for */
  127.     {look[temp1-(temp+1)] = argv[1][temp1];}
  128.     look[temp1-(temp+1)] = 0; /* null terminate this */
  129.  
  130.    }
  131.   }
  132.  
  133. /* get the drive we started in */
  134. get_drive(drive);
  135.  
  136. if (drive[1] == 255) /* if the default was for current drive, use it */
  137.  drive[1] = drive[0];
  138. else /* otherwise, normalize whatever they typed in to start with a=0 */
  139.  if ((drive[1] > 'A') && (drive[1] < 'Z'))
  140.    drive[1] = drive[1] - 'A';
  141.  else
  142.    drive[1] = drive[1] - 'a';
  143.  
  144. /* change to the starting drive */
  145. ret=chg_drive(drive[1]);
  146.  
  147. if (ret < drive[1])
  148.   printf("invalid drive selected...\n");
  149. else
  150.  {
  151.   /* get the directory we started in */
  152.   init_dir[0] = '\\';
  153.   get_dir(init_dir+1);
  154.  
  155.   if (start[0] == 0) /* if there was no starting path, use the current one */
  156.    strcpy(start,init_dir);
  157.  
  158.   /* do the actual work */
  159.   doit(look,start,flag1);
  160.  
  161.   /* change back to the initial drive */
  162.   chg_drive(drive[0]);
  163.  
  164.   /* now, change back to the initial directory */
  165.   chg_dir(init_dir);
  166.  } /* end else */
  167.  
  168. } /* end function */
  169.  
  170. doit(look,start,flag1)
  171. char *look,*start,flag1;
  172.  
  173. {
  174.  char file[3],name[128],*dirstak,curdir[140],*getmem();
  175.  int ret,tmp,top_ndx,bottom_ndx;
  176.  
  177.  dirstak = getmem(10000); /* get a hunk of memory for the directory queue */
  178.  if (dirstak == 0) /* if the getmem returned a null, error */
  179.  {printf("not enough memory...\n");
  180.   return;}
  181.  
  182. /* set the DTA to someplace we can use */
  183.  put_dta(name);
  184.  
  185.  top_ndx = 0;     /* set pointer to top of directory queue */
  186.  bottom_ndx = 0; /* set pointer to bottom of queue */
  187.  
  188.  /* put the starting directory in the queue */
  189.  for (tmp = 0; start[tmp] != 0; tmp++)
  190.   {dirstak[bottom_ndx++] = start[tmp];}
  191.  dirstak[bottom_ndx++] = 0;
  192.  
  193.  while (top_ndx != bottom_ndx)
  194.   {
  195.    /* check for any sub-directories */
  196.    ret = dirscan(file,name,curdir,dirstak,&top_ndx,&bottom_ndx);
  197.  
  198.    if (ret != 3)
  199.     {
  200.      /* run through the directory, querying for each file */
  201.      filscan(look,name);
  202.     }
  203.  
  204.    /* if only do this one directory, end here */
  205.    if (flag1 == 0)
  206.    {
  207.     rlsmem(dirstak,10000);
  208.     return(1);
  209.    }
  210.  
  211.   } /* end while loop */
  212.   rlsmem(dirstak,10000);
  213.  
  214. } /* end function */
  215.  
  216. dirscan(file,name,curdir,dirstak,top_ptr,bot_ptr)
  217. char *file,*name,*curdir,*dirstak;
  218. int *top_ptr,*bot_ptr;
  219. {
  220.  int ret,tmp,top_ndx,bottom_ndx,*p_file;
  221.  
  222.  bottom_ndx = *bot_ptr;
  223.  top_ndx = *top_ptr;
  224.  
  225.  /* initialize the file name for the directory search */
  226.  file[0] = '*';
  227.  file[1] = '.';
  228.  file[2] = 0;
  229.  
  230.  tmp = 0;
  231.  for (top_ndx; dirstak[top_ndx] != 0; top_ndx++)
  232.   { curdir[tmp++] = dirstak[top_ndx];}
  233.  curdir[tmp] = 0;
  234.  ++top_ndx;
  235.  ret = chg_dir(curdir);
  236.  if (ret != 3)
  237.   {
  238.    printf("\n   ON DIRECTORY %s\n",curdir);
  239.    find_dir(name,file,curdir,dirstak,&bottom_ndx);
  240.   }
  241.  *bot_ptr = bottom_ndx;
  242.  *top_ptr = top_ndx;
  243.  
  244.  return(ret);
  245. }
  246.  
  247. find_dir(name,file,curdir,dirstak,bot_ndx)
  248. char *name,*file,*curdir,*dirstak;
  249. int *bot_ndx;
  250. {
  251.  int ret,tmp,bottom_ndx;
  252.  unsigned temp;
  253.  
  254.  bottom_ndx = *bot_ndx; /* set the local variable = the real thing. */
  255.  
  256. /* search for first directory entry */
  257.  temp = 0x0010;
  258.  ret = srch1st(file,temp);
  259.  
  260. /* while the return from search is successful, check for dir attribute
  261.    and make sure it isn't a . or .. entry, put the whole pathname (null
  262.    terminated) at the bottom of the queue */
  263.  
  264.  while (ret != 18)
  265.  { if ((name[21] == 0x10) && (name[30] != '.'))
  266.    {
  267.     for (tmp = 0; curdir[tmp] != 0; tmp++)
  268.     {dirstak[bottom_ndx] = curdir[tmp];
  269.      ++bottom_ndx;}
  270.     if (curdir[1] != 0)
  271.      {dirstak[bottom_ndx++] = '\\';}
  272.    for (tmp = 30; name[tmp] != 0; tmp++)
  273.     {dirstak[bottom_ndx] = name[tmp];
  274.      ++bottom_ndx;}
  275.    dirstak[bottom_ndx++] = 0;
  276.  
  277.    } /* end if */
  278.     ret = srchnext(file); /* get another directory entry */
  279.  } /* end while */
  280.  
  281.  *bot_ndx = bottom_ndx; /*now restore the real value to its proper place */
  282.  
  283. } /* end function */
  284.  
  285. filscan(look,name)
  286. char *look,*name;
  287. {
  288.  int ret;
  289.  char tmp;
  290.  unsigned temp;
  291.  
  292.  temp = 0x0000;
  293.  ret = srch1st(look,temp); /* start looking for files */
  294.  
  295.  while (ret != 18)
  296.  {
  297.   printf("%s -->",name+30);
  298.   tmp = getch(); /* get the key directly from keyboard */
  299.   printf("%c\n",tmp); /* echo it back with <cr/lf> */
  300.   if ((tmp == 'y') || (tmp == 'Y'))
  301.     era_file(name+30);
  302.  
  303.   ret = srchnext(look); /* get another directory entry */
  304.  } /* end while */
  305.  
  306. } /* end function */
  307.  
  308. put_dta(p_dta)
  309. char *p_dta;
  310. {
  311.  union REGS inreg;
  312.  union REGS outreg;
  313.  
  314.  inreg.h.ah = 0x1a;
  315.  inreg.x.dx = p_dta;
  316.  
  317.  intdos(&inreg,&outreg);
  318.  
  319.  return(0);
  320. }
  321.  
  322. srch1st(p_file,attr)
  323. int *p_file;
  324. unsigned attr;
  325. {
  326.  union REGS inreg;
  327.  union REGS outreg;
  328.  
  329.  inreg.h.ah = 0x4e;
  330.  inreg.x.cx = attr;
  331.  inreg.x.dx = p_file;
  332.  
  333.  intdos(&inreg,&outreg);
  334.  
  335.  return(outreg.x.ax);
  336. }
  337.  
  338. srchnext(p_file)
  339. int *p_file;
  340. {
  341.  union REGS inreg;
  342.  union REGS outreg;
  343.  
  344.  inreg.h.ah = 0x4f;
  345.  
  346.  intdos(&inreg,&outreg);
  347.  
  348.  return(outreg.x.ax);
  349. }
  350.  
  351. chg_dir(curdir)
  352. char *curdir;
  353. {
  354.  union REGS inreg;
  355.  union REGS outreg;
  356.  
  357.  inreg.h.ah = 0x3b;
  358.  inreg.x.dx = curdir;
  359.  
  360.  intdos(&inreg,&outreg);
  361.  
  362.  return(outreg.x.ax);
  363. }
  364.  
  365. get_dir(temp)
  366. char *temp;
  367. {
  368.  union REGS inreg;
  369.  union REGS outreg;
  370.  
  371.  inreg.h.ah = 0x47;
  372.  inreg.h.dl = 0; /* relative drive */
  373.  inreg.x.si = temp; /* where to put the pathname */
  374.  
  375.  intdos(&inreg,&outreg);
  376.  
  377.  return(outreg.x.ax);
  378. }
  379.  
  380. get_drive(where)
  381. char *where;
  382. {
  383.  union REGS inreg;
  384.  union REGS outreg;
  385.  
  386.  inreg.h.ah = 0x19;
  387.  
  388.  intdos(&inreg,&outreg);
  389.  
  390.  *where = outreg.h.al;
  391. }
  392.  
  393. era_file(which)
  394. char *which;
  395. {
  396.  union REGS inreg;
  397.  union REGS outreg;
  398.  
  399.  inreg.h.ah = 0x41;
  400.  inreg.x.dx = which; /* pointer to filename */
  401.  
  402.  intdos(&inreg,&outreg);
  403.  
  404.  /* there's no easy way to check for errors, so don't even do it.
  405.     dos returns error flag in carry flag, LATTICE C can't access it without
  406.     your own assembler routine. I have one, but it's a bit hairy. For those
  407.     who insist on doing things right, drop me a note. jjw */
  408. }
  409.  
  410. chg_drive(drive)
  411. char drive;
  412. {
  413.  union REGS inreg;
  414.  union REGS outreg;
  415.  
  416.  inreg.h.ah = 0x0e;
  417.  inreg.h.dl = drive;
  418.  
  419.  intdos(&inreg,&outreg);
  420.  
  421.  return(outreg.h.al);
  422. }
  423.